#include "DKInclude.h"

DKActor::DKActor() : CCSprite()
{
	this->isMoving=false;
	this->movingVelocity = 1;
}

DKActor::~DKActor()
{

}

DKActor * DKActor::create(DKActorType actorType, int initXIndex = 0, int initYIndex = 0)
{
	DKActor *result;
	
	switch(actorType)
	{	
	case DKActorType_TheMan:
		result = new DKActorTheMan();
		break;

	case DKActorType_Grass:
		result = new DKActorGrass();
		break;

	case DKActorType_Stone:
		result= new DKActorStone();
		break;

	case DKActorType_Box:
		result = new DKActorBox();
		break;

	case DKActorType_Lazer_Machine:
		result = new DKActorLazerMachine();
		break;

	case DKActorType_Lazer:
		result = new DKActorLaser();
		break;

	}
	
	result->location = DKPoint(initXIndex, initYIndex);
	result->actorType = actorType;

	result->initWithFile(result->imagePath->getCString(), CCRect(0, 0, ACTOR_SIZE, ACTOR_SIZE));
	result->setPosition(result->getScreenPoint(result->location));
	
	return result;
}


cocos2d::CCPoint DKActor::getScreenPoint(DKPoint indexPoint)
{
	return ccp(indexPoint.XIndex * ACTOR_SIZE + ACTOR_SIZE / 2, indexPoint.YIndex * ACTOR_SIZE + ACTOR_SIZE / 2);
}

DKPoint DKActor::getIndexPoint(CCPoint screenPoint)
{
	int xIndex = (int)screenPoint.x / ACTOR_SIZE;
	int yIndex = (int)screenPoint.y / ACTOR_SIZE;
	return DKPoint(xIndex , yIndex);
}

bool DKActor::moveToDKPoint(DKPoint point)
{
	if(this->isMoving) return false;
	this->isMoving = true;
	this->location = point;
	
	CCPoint targetPoint = getScreenPoint(point);
	// Determine the length of how far we're shooting
    int offRealX = targetPoint.x - this->getPosition().x;
    int offRealY = targetPoint.y - this->getPosition().y;
    float length = sqrtf((offRealX * offRealX) 
                                        + (offRealY*offRealY));
    float velocity = ACTOR_SIZE * movingVelocity * 5; // pixels/1sec
    float duration = length/velocity;

    // Move projectile to actual endpoint
    this->runAction( CCSequence::create(
        CCMoveTo::create(duration, targetPoint),
        CCCallFuncN::create(this,  callfuncN_selector(DKActor::onMoveFinished)), 
        NULL) );
	return true;
}

bool DKActor::moveToPositionScreen(CCPoint screenPosition)
{
	return moveToDKPoint(this->getIndexPoint(screenPosition));
}

bool DKActor::moveAsDirection( DKEventDirection direction )
{
	DKPoint point = this->location;
	switch(direction)
	{
	case DKEventDirection_Down: point.YIndex--; break;
	case DKEventDirection_Up: point.YIndex++; break;
	case DKEventDirection_Left: point.XIndex--; break;
	case DKEventDirection_Right: point.XIndex++; break;
	}
	return moveToDKPoint(point);
}

void DKActor::onMoveFinished(CCNode* sender)
{
	DKActor *actor = (DKActor *)sender;
	actor->isMoving = false;
}

DKAction * DKActor::BePushed( DKEvent *evt, CCObject *map )
{
	DKMap *mapObject = (DKMap *)map;
	DKActor *actor = (DKActor *)evt->Actor;
	DKActor *nextActor = mapObject->GetActorAt(actor->location.MoveToDirection(evt->Direction));

	DKAction *receiverAction = DKConfiguration::getReceiverAction(evt->Direction, actor, nextActor);
	DKAction *actualReceiverAction = NULL;
	//Process receiver
	switch(receiverAction->actionType)
	{
	case DKActionType_MoveTo:
		DKEvent *nextEvent = new DKEvent(nextActor, DKEventType_Push, evt->Direction);
		actualReceiverAction = BePushed(nextEvent, map);
		break;
	}

	//Process sender
	DKAction * senderAction = DKConfiguration::getSenderAction(evt->Direction, actor, nextActor);
	switch(senderAction->actionType)
	{
	case DKActionType_MoveTo:
			if(actualReceiverAction != NULL && actualReceiverAction->actionType != DKActionType_None)
			{
				actor->moveAsDirection(senderAction->direction);
				return senderAction;
			}
			break;
	case DKActionType_SlipOn:
		actor->moveAsDirection(senderAction->direction);
		return senderAction;
	}
	return NULL;
}

